# -*- coding: utf-8 -*-
# Copyright © 2024 weidongkl <weidongkx@gmail.com>

from excavator.db.meta.fields import Field
from excavator.db.meta.json_model import get, save


class ModelBase(type):

    def __new__(mcs, name, bases, attrs):
        # If this isn't a subclass of Model, don't do anything special.
        if not bases:
            return type.__new__(mcs, name, bases, attrs)
        fields = []
        for obj_name, obj in attrs.items():
            if isinstance(obj, Field):
                obj.set_name(obj_name)
                fields.append(obj)
        for i in fields:
            attrs.pop(i.name)
        attrs['fields'] = fields
        new_class = type.__new__(mcs, name, bases, attrs)
        return new_class


# noinspection PyCompatibility
class Model(object, metaclass=ModelBase):
    def __init__(self, **kwargs):
        resp = dict()
        if len(kwargs) == 0:
            return
        for field in self.fields:
            # TODO: update default value to field default value
            resp[field.name] = field.to_representation(kwargs.get(field.name, None))
            setattr(self, field.name, kwargs.get(field.name, None))
        self.resp = resp

    def dump(self):
        return self.resp

    def save(self):
        """store data"""
        save(self.__class__.__name__, self.resp)

    def update(self, **kwargs):
        for field in self.fields:
            for k, v in kwargs.items():
                if field.name == k:
                    self.resp[field.name] = field.to_representation(v)
                    setattr(self, k, v)
        self.save()

    @classmethod
    def load(cls):
        "load data"
        return get(cls.__name__)

    @classmethod
    def create(cls, **kwargs):
        obj = cls(**kwargs)
        obj.save()
        return obj

    @classmethod
    def get(cls):
        obj = cls()
        data = cls.load()
        if data is None:
            return None
        obj.resp = data
        for field in cls.fields:
            # TODO: update default value to field default value
            setattr(obj, field.name, field.to_internal_value(data.get(field.name, None)))
        return obj
